package com.lightsh.handwritten;

import java.util.ArrayList;
import java.util.regex.Pattern;

import com.lightsh.common.CharacterFillHelper;
import com.lightsh.common.CharacterItem;
import com.lightsh.common.NoteItem;
import com.lightsh.db.DbDataHelper;
import com.lightsh.db.MyDbHelper;
import com.lightsh.utility.Constants;
import com.lightsh.utility.Utility;

import android.app.Activity;
import android.content.Context;
import android.gesture.Gesture;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGestureListener;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class HandwrittingActivity extends Activity implements OnClickListener{
	private static final String TAG = "HandwrittingActivity";
	private static final boolean DEBUG = Constants.DEBUG;
	
	public static final String EXTRA_NOTE_ID = "ExtraNoteId";
	
    private GestureOverlayView mGestureOverlay;
    private EditText mEdit;
    private KeyListener mOldKeyListener;
    private ArrayList<CharacterItem> mCharacterBitmapList = new ArrayList<CharacterItem>();
    private String mText;
    private long mTime;
    
    public static final int INVALID_ID = NoteItem.INVALID_ID;
    private long mId = INVALID_ID;
    private boolean mbChange = false;
    
    private int mImageSize = 80;
    private int mImageColor = Color.BLUE;
    private float mStrokeWidth = 10.0f;
    private final static String sFlag = Constants.PIC_FLAG;
    
    private Button mDeleteBtn;
    private Button mSwitchKeyboardBtn;
    private TextView mDateTextView;
    private View mInputLayout;
    private boolean mbShowNormalKeyboard = false;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.handwriting_layout);        
        initWidget();
        
        Bundle bundle = getIntent().getExtras();
        if(bundle != null && bundle.containsKey(EXTRA_NOTE_ID)){
        	mId = bundle.getLong(EXTRA_NOTE_ID);
        }
        getNoteInfo();
    }
    
    private int getBitmapIndexBaseText(String text, int textPos){
    	int index = -1;
    	int tempIndex = text.indexOf(sFlag);
    	while(tempIndex != -1 && tempIndex <= textPos){
    		index++;
    		tempIndex = text.indexOf(sFlag, tempIndex + sFlag.length());
    	}
    	return index;
    }
    
    private void initWidget(){
    	mInputLayout = findViewById(R.id.gestureLayout);
    	mGestureOverlay = (GestureOverlayView) findViewById(R.id.gestureOverlay);
        
        int activityWidth = getWindowManager().getDefaultDisplay().getWidth();
        LayoutParams params = mGestureOverlay.getLayoutParams();
        
        int btnLayoutWidth = findViewById(R.id.btnLayout).getLayoutParams().width;           
        params.height = activityWidth - btnLayoutWidth;
        
        mGestureOverlay.setGestureStrokeAngleThreshold(0);
        mGestureOverlay.setGestureStrokeLengthThreshold(0);
        mGestureOverlay.setGestureStrokeSquarenessTreshold(0);
        mGestureOverlay.addOnGestureListener(new OnGestureListener() {
			
			@Override
			public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onGesture(GestureOverlayView overlay, MotionEvent event) {
				// TODO Auto-generated method stub
				
			}
		});
        
        mGestureOverlay.addOnGesturePerformedListener(new OnGesturePerformedListener() {
			
			@Override
			public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
				addGestureToScrollView(gesture);
			}
		});
    	
    	
    	mDeleteBtn = (Button)findViewById(R.id.btnDelete);
    	mSwitchKeyboardBtn = (Button) findViewById(R.id.btnSwitchKeyboard);
    	mDateTextView = (TextView)findViewById(R.id.dateTextView);
    	
    	mEdit = (EditText)findViewById(R.id.imageEdit);
        
        mEdit.addTextChangedListener(new TextWatcher() {
			
			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
			}
			
			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				try{
					if(count > after
							&& sFlag.equals(s.subSequence(start, start + count - after).toString())){
						
						int index = getBitmapIndexBaseText(s.toString(), start);
						if(index >= 0 && mCharacterBitmapList.size() > index){
							mCharacterBitmapList.remove(index);
						}else{
							Log.e(TAG, "cant found right bitmap to delete = " + index);
						}
					}
					mbChange = true;
				}catch(Exception e){
					e.printStackTrace();
				}
			}
			
			@Override
			public void afterTextChanged(Editable s) {
				
			}
		});
        
        mEdit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
			
			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				log("onFocusChange = " + hasFocus);
				
			}
		});
        mEdit.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				visibleInputLayout(true);
				
			}
		});
        mOldKeyListener = mEdit.getKeyListener();
        mEdit.setKeyListener(mKeyListener);
    }
    private boolean visibleInputLayout(boolean forceToShow){
    	if(forceToShow && !mbShowNormalKeyboard){
    		if(mInputLayout.getVisibility() != View.VISIBLE){
				mInputLayout.setVisibility(View.VISIBLE);
				return true;
			}
    	}else{
    		if(mInputLayout.getVisibility() == View.VISIBLE){
    			mInputLayout.setVisibility(View.GONE);
    			return true;
    		}
    	}
    	return false;
    }
    
    private void addGestureToScrollView(Gesture gesture){
    	Bitmap bitmap = Utility.gestureToBitmap(gesture, mImageSize, mImageSize, mImageColor, mStrokeWidth, ((float)mImageSize)/getWindowManager().getDefaultDisplay().getWidth());
    	mbChange = true;
    	int index = addCharacterToView(bitmap);
    	if(index < mCharacterBitmapList.size()){
    		log("add index = " + index);
    		mCharacterBitmapList.add(index, new CharacterItem(bitmap));
    	}else{
    		mCharacterBitmapList.add(new CharacterItem(bitmap));
    	}
    }
    /**
     * 将字符的bitmap添加到需要显示的Edit中，返回他前面包含几个character的bitmap
     * @param bitmap
     */
    private int addCharacterToView(Bitmap bitmap){    	
    	int selectionStart = mEdit.getSelectionStart();
    	SpannableStringBuilder builder = CharacterFillHelper.appendBitmapToString(this, (SpannableStringBuilder) mEdit.getEditableText(), 
    			selectionStart, bitmap);
    	return getBitmapIndexBaseText(builder.toString(), selectionStart);
    }
    
    private void getNoteInfo(){
    	if(mId != INVALID_ID){
    		NoteItem item = DbDataHelper.getNoteInfo(this, mId);
    		DbDataHelper.getNoteCharacterList(this, mId, mCharacterBitmapList);
    		if(item != null){
    			mText = item.getText();
    			mTime = item.getLastlyTime();
    		}    		
    		// 添加数据
    		fillCharacters();
    	}else{
    		mTime = System.currentTimeMillis();
    	}
    	mDateTextView.setText(Utility.formatTime(mTime));
    }
    private void fillCharacters(){
    	mEdit.setText(CharacterFillHelper.getCharaterString(this, mText, mCharacterBitmapList));
    	mEdit.setSelection(mEdit.getText().length());
    	mbChange = false;
    }
    
    @Override
	public void onBackPressed() {
    	if(visibleInputLayout(false)){
    		return;
    	}
    	saveCharacterList();
		super.onBackPressed();
	}
    private void saveCharacterList(){
    	final String text =  mEdit.getText().toString();
    	if(mId != INVALID_ID){
    		if(!mbChange){
    			return;
    		}
    	}else{
    		if(text.length() == 0 && (mCharacterBitmapList == null || mCharacterBitmapList.size() == 0)){
    			return;
    		}
    	}
    	boolean bSuccess = DbDataHelper.saveNoteInfo(this, mId, text, mCharacterBitmapList);
    	if(!bSuccess){
    		Toast.makeText(this, R.string.saveFail, Toast.LENGTH_LONG).show();
    		return;
    	}
    	setResult(Activity.RESULT_OK);
    }
    
	private void log(String tip){
    	if(DEBUG){
    		Log.d(TAG, "" + tip);
    	}    	
    }
	private void logE(String tip){
    	Log.e(TAG, "" + tip); 	
    }

	@Override
	public void onClick(View v) {
		switch(v.getId()){
		case R.id.btnDelete:
			dispatchDelete();
			break;
		case R.id.btnSwitchKeyboard:
			switchKeyboard();
			break;
		case R.id.btnEnter:
			dispatchEnter();
			break;
		}
		
	}
	private void dispatchDelete(){
		mEdit.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
	}
	private void dispatchEnter(){
		mEdit.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
	}
	private void switchKeyboard(){
		mbShowNormalKeyboard = !mbShowNormalKeyboard;
		showKeyboard();
	}
	private void showKeyboard(){
		if(mbShowNormalKeyboard){
			visibleInputLayout(false);
			visibleNormalKeyboard(true);
		}else{
			visibleInputLayout(true);
			visibleNormalKeyboard(false);
		}
	}
	private void visibleNormalKeyboard(boolean forceToShow){
		if(forceToShow && mbShowNormalKeyboard){
			// show
//			getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
			mEdit.postDelayed(new Runnable() {				
				@Override
				public void run() {
					InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
					imm.toggleSoftInputFromWindow(mEdit.getApplicationWindowToken(), 0, InputMethodManager.HIDE_NOT_ALWAYS);
//					imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
//					imm.showSoftInputFromInputMethod(mEdit.getWindowToken(), InputMethodManager.SHOW_IMPLICIT);
				}
			}, 200);
		}else{
			InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 
//			getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED);
//			mEdit.setInputType(mEdit.getInputType() | InputType.TYPE_NULL);
			imm.hideSoftInputFromWindow(mEdit.getWindowToken(), 0);
		}
		mEdit.setKeyListener(mKeyListener);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, 0, 0, R.string.switchKeyboard);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()){
		case 0:
			switchKeyboard();
			break;
		}
		return super.onOptionsItemSelected(item);
	}
	
	private KeyListener mKeyListener = new KeyListener() {		
		@Override
		public boolean onKeyUp(View view, Editable text, int keyCode, KeyEvent event) {
			return mOldKeyListener.onKeyUp(view, text, keyCode, event);
		}
		
		@Override
		public boolean onKeyOther(View view, Editable text, KeyEvent event) {
			return mOldKeyListener.onKeyOther(view, text, event);
		}		
		@Override
		public boolean onKeyDown(View view, Editable text, int keyCode,
				KeyEvent event) {
			return mOldKeyListener.onKeyDown(view, text, keyCode, event);
		}		
		@Override
		public int getInputType() {
			if(mbShowNormalKeyboard){
				return InputType.TYPE_CLASS_TEXT;
			}else{
				return InputType.TYPE_NULL;
			}
		}		
		@Override
		public void clearMetaKeyState(View view, Editable content, int states) {
			mOldKeyListener.clearMetaKeyState(view, content, states);
		}
		
	};
	
}